package com.jet.office.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jet.core.utils.IdUtil;
import com.jet.office.domain.dto.IndustryMerchantActiveDto;
import com.jet.office.domain.dto.IndustryMerchantCallbackDto;
import com.jet.office.domain.dto.OfficeOrderCreateDto;
import com.jet.office.domain.entity.*;
import com.jet.office.domain.enums.IndustryType;
import com.jet.office.domain.enums.OfficeOrderStatus;
import com.jet.office.domain.vo.IndustryActiveVo;
import com.jet.office.domain.vo.MerchantIndustryInfoVo;
import com.jet.office.domain.vo.OfficeOrderCreateVo;
import com.jet.office.domain.vo.PackageSpuListVo;
import com.jet.office.mapper.MerchantIndustryMapper;
import com.jet.office.service.IMerchantIndustryLogService;
import com.jet.office.service.IMerchantIndustryService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-02-14
 */
@Service

public class MerchantIndustryServiceImpl extends ServiceImpl<MerchantIndustryMapper, MerchantIndustry> implements IMerchantIndustryService {

    private final IndustryService industryService;
    private final IndustryAttrService industryAttrService;
    private final IMerchantIndustryLogService merchantIndustryLogService;
    private final OfficeOrderService officeOrderService;
    private final PackageSpuService packageSpuService;
    private final PackageSkuService packageSkuService;

    @Lazy
    public MerchantIndustryServiceImpl(IndustryService industryService, IndustryAttrService industryAttrService, IMerchantIndustryLogService merchantIndustryLogService, OfficeOrderService officeOrderService, PackageSpuService packageSpuService, PackageSkuService packageSkuService) {
        this.industryService = industryService;
        this.industryAttrService = industryAttrService;
        this.merchantIndustryLogService = merchantIndustryLogService;
        this.officeOrderService = officeOrderService;
        this.packageSpuService = packageSpuService;
        this.packageSkuService = packageSkuService;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IndustryActiveVo industryActive(IndustryMerchantActiveDto dto) {
        //版本开通时，判断是否有开通版本，如果没有开通则新开通
        //如果已到期，则按当前日期开始开通
        //如果未到期，则按实际到期日期开始开通
        IndustryActiveVo vo = new IndustryActiveVo();
        MerchantIndustry industryMerchant = findByMerchantNo(dto.getMerchantNo());
        if (industryMerchant == null) {
            save(dto.getMerchantNo(), dto.getIndustryId(), dto.getIndustryType(), dto.getAddMonth());
        } else {
            industryActive(industryMerchant.getId(), dto.getIndustryId(), dto.getIndustryType(),
                    industryMerchant.getExpireDate(), dto.getAddMonth());
        }
        merchantIndustryLogService.save(dto.getMerchantNo(), dto.getOrderId(), dto.getIndustryId(),
                dto.getIndustryType(), dto.getAddMonth());
        vo.setStatus(1);
        vo.setActiveTime(LocalDateTime.now());
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IndustryActiveVo industryCallback(IndustryMerchantCallbackDto dto) {
        IndustryActiveVo vo = new IndustryActiveVo();
        MerchantIndustry industryMerchant = findByIndustryId(dto.getIndustryId());
        if (industryMerchant != null) {
            industryCallback(industryMerchant.getId(), dto.getIndustryId(), industryMerchant.getType(),
                    industryMerchant.getExpireDate(), dto.getCallbackMonth());
            merchantIndustryLogService.save(dto.getMerchantNo(), dto.getOrderId(), dto.getIndustryId(),
                    industryMerchant.getType(), dto.getCallbackMonth());
        }
        vo.setStatus(1);
        vo.setActiveTime(LocalDateTime.now());
        return vo;
    }

    @Override
    public void industryActive(String id, String industryId, int industryType, LocalDate expireDate, long addMonth) {
        LocalDate now = LocalDate.now();
        LocalDate endDate = expireDate;
        if (expireDate.isBefore(now)) {
            endDate = now.plusMonths(addMonth);
        } else {
            endDate = endDate.plusMonths(addMonth);
        }
        MerchantIndustry entity = new MerchantIndustry();
        entity.setId(id);
        entity.setIndustryId(industryId);
        entity.setType(industryType);
        entity.setExpireDate(endDate);
        super.updateById(entity);
    }

    @Override
    public void industryCallback(String id, String industryId, int industryType, LocalDate expireDate, long callbackMonth) {
        LocalDate endDate = expireDate.plusMonths(callbackMonth);
        MerchantIndustry entity = new MerchantIndustry();
        entity.setId(id);
        entity.setExpireDate(endDate);
        super.updateById(entity);
    }

    @Override
    public void save(long merchantNo, String industryId, int industryType, long addMonth) {
        LocalDate now = LocalDate.now();
        LocalDate expireDate = now.plusMonths(addMonth);
        MerchantIndustry entity = new MerchantIndustry();
        entity.setId(IdUtil.generateLower());
        entity.setMerchantNo(merchantNo);
        entity.setIndustryId(industryId);
        entity.setExpireDate(expireDate);
        entity.setType(industryType);
        entity.setCreateTime(LocalDateTime.now());
        entity.setUpdateTime(LocalDateTime.now());
        super.save(entity);
    }

    @Override
    public MerchantIndustry findByIndustryId(String industryId) {
        Wrapper<MerchantIndustry> wrapper = new LambdaQueryWrapper<MerchantIndustry>()
                .eq(MerchantIndustry::getIndustryId, industryId);
        return super.getOne(wrapper);
    }

    @Override
    public MerchantIndustry findByMerchantNo(long merchantNo) {
        Wrapper<MerchantIndustry> wrapper = new LambdaQueryWrapper<MerchantIndustry>()
                .eq(MerchantIndustry::getMerchantNo, merchantNo);
        return super.getOne(wrapper);
    }

    @Override
    public MerchantIndustryInfoVo industryInfo(long merchantNo) {
        MerchantIndustryInfoVo vo = new MerchantIndustryInfoVo();
        MerchantIndustry industryMerchant = findByMerchantNo(merchantNo);
        if (industryMerchant == null) {
            return null;
        }
        BeanUtils.copyProperties(industryMerchant, vo);
        IndustryEntity industry = industryService.findById(vo.getIndustryId());
        if (industry != null) {
            vo.setIndustryName(industry.getName());
        }
        return vo;
    }

    @Override
    public List<IndustryAttrEntity> merchantChargeAbility(long merchantNo) {
        LocalDate now = LocalDate.now();
        MerchantIndustryInfoVo industryMerchantInfo = industryInfo(merchantNo);
        if (industryMerchantInfo == null || industryMerchantInfo.getExpireDate().isBefore(now)) {
            List<IndustryAttrEntity> attrs = industryAttrService.findAll();
            return attrs.stream().filter(IndustryAttrEntity::isFee).collect(Collectors.toList());
        }
        return industryAttrService.findAllByIndustryId(industryMerchantInfo.getIndustryId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void industryTrial(long merchantNo, long storeNo, String accountId) {
        // 获取体验版本
        List<PackageSpuListVo> list = packageSpuService.findAll();
        PackageSpuListVo spu = list.stream().filter(x -> x.getType() == IndustryType.trial_edition.getCode())
                .findFirst().orElse(null);
        if (spu == null) {
            return;
        }
        List<PackageSkuEntity> skus = packageSkuService.findAllBySpuId(spu.getId());
        PackageSkuEntity sku = skus.stream().findFirst().orElse(null);
        if (sku == null) {
            return;
        }
        OfficeOrderCreateDto dto = new OfficeOrderCreateDto();
        dto.setSkuId(sku.getId());

        OfficeOrderCreateVo createVo = officeOrderService.create(merchantNo, storeNo, accountId, dto);
        officeOrderService.trialPayResult(merchantNo, storeNo, createVo.getOrderId(),
                OfficeOrderStatus.waitPay.getCode());
    }
}
